//
//  main.m
//  OC02_实例变量可见度_方法
//
//  Created by dllo on 16/2/25.
//  Copyright © 2016年 Apon. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
    
    
#pragma mark - 知识点1. 实例(成员)变量可见度
/**
 * 3种: @public, @protected, @private.
 * 默认: @protected.
 *
 * 3种之间的区别: @public: 本类可以直接访问(->).
                         子类可以直接访问.
                         其它类 可以直接访问.
 
                @protected: 本类 可以直接访问.
                            子类 可以直接访问.
                            其它类 不可以直接访问.
 
                @private: 本类 可以直接访问.
                          子类 不可以直接访问.
                          其它类 不可以直接访问.
 
 * 详见Person.h 文件.
 */
#pragma mark - 知识点2. 方法
/**
 * [接收者 消息]
 *
 * 接收者: 类和对象.
 * 消息(方法): 类方法(+)和对象方法(-).
 * 
 * 详见 Person.h文件.
 */
#if 0
#pragma mark - 知识点3. setter, getter 方法.
/**
 * 一个实例变量要有一堆setter, getter方法.
 * setter方法目的, 对实例变量赋值.
 * getter方法目的, 对实例变量取值.
 *
 * 详见: Person.h 文件.
 */
    
    //创建对象.
    Person *person1 = [[Person alloc] init];
    
    //调用setter方法.
    [person1 setName:@"zhangsan"];
    
    //调用getter方法.
    [person1 name];
    
    NSString *str = [person1 name];
    
    NSLog(@"str:%@", str);
    
    //创建person2对象
    Person *person2 = [[Person alloc] init];
    
    [person2 setName:@"Tom"];
    
    [person2 setName:@"Lisi"];
    
    NSLog(@"%@", [person2 name]);
    
    
    //注意: 下面的person3并没有开辟新的内存空间, 只是指针指向了person2内存首地址.
    
    Person *person3 = person2;
    
    NSLog(@"%@", person3.name);
    
    
    
    
    
#pragma mark - 知识点4. 继承
/**     
 * 子类继承父类 所有的实例变量和方法.
 * OC中, 只有子类和父类两层.
 * OC中是单向继承.
 * 继承有传递性.
 *
 * Student继承于Person类, CollegeStudent类继承于Studen类.
 * 详见: Student, CollegeStudent类文件.
 */
    
    //创建学生对象.
    Student *stu1 = [[Student alloc] init];
    
    //SetName方法是从父类继承下来的.
    [stu1 setName:@"小明"];
    
    [stu1 name:@"小明" sex:@"male" age:18];
    
    [stu1 sayHi];
    
    
#pragma mark - 知识点5. 重写父类方法(overwrite).
/**
 * 父类方法无法满足子类需求.
 * 重写父类方法一般是在父类方法的基础上,添加新的代码段.
 * 详见 Student.m文件.
 */
    
    
    //创建一个student对象.
    Student *student1 = [[Student alloc] init];
    
    [student1 name:@"wangwu" sex:@"male" age:20];
    [student1 setGrade:80];
    [student1 setClassroomName:@"DLS160101"];
    
    
    //调用sayHi方法.
    [student1 sayHi];
    

#pragma mark - 知识点6. 重写初始化方法.
/**
 * Person类 重写 父类的init方法.
 * 详见 Person.m 文件.
 */
    
    // 创建一个Person对象.
    Person *per1 = [[Person alloc] init];
    [per1 sayHi];
    
    // 创建一个Student对象.
    Student *stu = [[Student alloc] init];
    [stu sayHi];
    
#endif
    
#pragma mark - 知识点7. 自定义初始化方法.
/** 
 * 需求: 通过一个方法, 实现了初始化, 同时给某些实际变量赋值.
 *
 * 详见 Person.h, Person.m文件.
 */
    
    
    // 创建Person对象.
    Person *per1 = [[Person alloc] initWithName:@"Tom"];
    
    [per1 sayHi];
    
    
    
    Person *per2 = [[Person alloc] initWithName:@"张三" sex:@"male" age:20];
    [per2 sayHi];
    

#pragma mark - 知识点8. 构造器
    /** 
     * 构造器就是方法.
     * + 方法.
     * 封装了对象创建和初始化过程.
     *
     * 详见Person类文件.
     */
    
    // 创建对象.(使用构造器方法).
    Person *per3 = [Person person];
    [per3 sayHi];
    
    Person *per4 = [Person personWithName:@"xuhao" sex:@"male" age:87];
    [per4 sayHi];
    
    
    
    
    
    
    
    
    
    
    
    
    
    return 0;
}
